// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.warehouse.viewers.xml;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.datatools.connectivity.oda.OdaException;
import org.eclipse.datatools.enablement.oda.xml.util.ui.ATreeNode;
import org.eclipse.datatools.enablement.oda.xml.util.ui.SchemaPopulationUtil;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf Qiang.Zhang.Adolf@gmail.com 2008-5-22 qiang.zhang $
 * 
 */
public class TreePopulator {

    private final Tree availableXmlTree;

    private final Map<String, TreeItem> xPathToTreeItem = new HashMap<String, TreeItem>();

    private final Map<String, ATreeNode> xPathToNode = new HashMap<String, ATreeNode>();

    private String filePath;

    private static int limit;

    /**
     * Qiang.Zhang.Adolf@gmail.com TreePopulator constructor comment.
     * 
     * @param availableXmlTree
     */
    public TreePopulator(Tree availableXmlTree) {
        super();
        this.availableXmlTree = availableXmlTree;
    }

    /**
     * populate xml tree.
     * 
     */
    public boolean populateTree(String filePath, ATreeNode treeNode) {
        availableXmlTree.removeAll();
        xPathToTreeItem.clear();
        xPathToNode.clear();
        if (filePath != null && !filePath.equals("")) { //$NON-NLS-1$
            try {
                treeNode = SchemaPopulationUtil.getSchemaTree(filePath, true, limit);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (OdaException e) {
                e.printStackTrace();
            } catch (URISyntaxException e) {
                e.printStackTrace();
            } catch (Exception e) {
                return false;
            }
            if (treeNode == null || treeNode.getChildren().length == 0) {
                // OdaException ex = new OdaException(Messages.getString("dataset.error.populateXMLTree"));
                // //$NON-NLS-1$
                // ExceptionHandler.process(ex);
                return false;
            } else {
                Object[] childs = treeNode.getChildren();
                populateTreeItems(availableXmlTree, childs, 0, ""); //$NON-NLS-1$
                this.filePath = filePath;
                return true;
            }
        }
        return false;
    }

    /**
     * populate tree items.
     * 
     * @param tree
     * @param node
     */
    private void populateTreeItems(Object tree, Object[] node, int level, String parentXPath) {
        level++;
        if (level > 10) {
            return;
        } else {
            for (int i = 0; i < node.length; i++) {
                TreeItem treeItem;
                if (tree instanceof Tree) {
                    treeItem = new TreeItem((Tree) tree, 0);
                } else {
                    treeItem = new TreeItem((TreeItem) tree, 0);
                }

                ATreeNode treeNode = (ATreeNode) node[i];
                treeItem.setData(treeNode);
                int type = treeNode.getType();
                if (type == ATreeNode.ATTRIBUTE_TYPE) {
                    treeItem.setText("@" + treeNode.getValue().toString()); //$NON-NLS-1$
                } else {
                    treeItem.setText(treeNode.getValue().toString());
                }

                String currentXPath = parentXPath + "/" + treeItem.getText(); //$NON-NLS-1$
                xPathToTreeItem.put(currentXPath, treeItem);
                xPathToNode.put(currentXPath, treeNode);

                if (treeNode.getChildren() != null && treeNode.getChildren().length > 0) {
                    populateTreeItems(treeItem, treeNode.getChildren(), level, currentXPath);
                }
                setExpanded(treeItem);
            }
        }
    }

    // expand the tree
    private void setExpanded(TreeItem treeItem) {
        if (treeItem.getParentItem() != null) {
            setExpanded(treeItem.getParentItem());
        }
        treeItem.setExpanded(true);
    }

    public TreeItem getTreeItem(String absoluteXPath) {
        return (TreeItem) xPathToTreeItem.get(absoluteXPath);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getAbsoluteXPath".
     * 
     * @param treeItem
     * @return
     */
    public String getAbsoluteXPath(TreeItem treeItem) {
        for (String key : xPathToTreeItem.keySet()) {
            if (xPathToTreeItem.get(key).equals(treeItem)) {
                return key;
            }
        }
        return null;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getAbsoluteXPath".
     * 
     * @param treeNode
     * @return
     */
    public String getAbsoluteXPath(ATreeNode treeNode) {
        for (String key : xPathToNode.keySet()) {
            if (xPathToNode.get(key).equals(treeNode)) {
                return key;
            }
        }
        return null;
    }

    /**
     * Getter for filePath.
     * 
     * @return the filePath
     */
    public String getFilePath() {
        return this.filePath;
    }

    public static int getMaximumRowsToPreview() {
        return 50;
    }

    /**
     * Sets the limit.
     * 
     * @param limit the limit to set
     */
    public void setLimit(int lit) {
        limit = lit;
    }

    /**
     * Getter for limit.
     * 
     * @return the limit
     */
    public static int getLimit() {
        return limit;
    }

}
